package com.dmz.workflow.util;


import com.alibaba.fastjson.JSONArray;
import com.dmz.workflow.constant.ELConstant;
import com.dmz.workflow.constant.FormComponentConstants;
import com.dmz.workflow.constant.LanguageExpressionConstants;
import com.dmz.workflow.dto.ConditionOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;

import java.util.Collections;
import java.util.List;

/**
 * EL 表达式工具类
 */
@Slf4j
public class ElExpressionUtil {

    /**
     * 根据逻辑运算符产生EL表达式
     *
     * @param conditionOperationList 操作符和数值列表
     * @return EL表达式
     */
    public static String generateElExpression(List<ConditionOperation> conditionOperationList) {
        StringBuilder elExpression = new StringBuilder();
        if (ObjectUtils.isEmpty(conditionOperationList)) {
            return "";
        }
        int length = conditionOperationList.size();
        elExpression.append(ELConstant.EL_VAR_CONSTANT).append(ELConstant.EL_FRONT_BRACE_CONSTANT);
        for (int i = 0; i < conditionOperationList.size(); i++) {
            String valueStr;
            switch (conditionOperationList.get(i).getOperation()) {
                case ELConstant.EL_BIGGER_CONSTANT:
                    elExpression.append(conditionOperationList.get(i).getFormKey()).append(ELConstant.EL_BIGGER_CONSTANT).append(conditionOperationList.get(i).getValue());
                    break;
                case ELConstant.EL_BIGGER_AND_EQUAL_CONSTANT:
                    elExpression.append(conditionOperationList.get(i).getFormKey()).append(ELConstant.EL_BIGGER_AND_EQUAL_CONSTANT).append(conditionOperationList.get(i).getValue());
                    break;
                case ELConstant.EL_SMALLER_CONSTANT:
                    elExpression.append(conditionOperationList.get(i).getFormKey()).append(ELConstant.EL_SMALLER_CONSTANT).append(conditionOperationList.get(i).getValue());
                    break;
                case ELConstant.EL_SMALLER_AND_EQUAL_CONSTANT:
                    elExpression.append(conditionOperationList.get(i).getFormKey()).append(ELConstant.EL_SMALLER_AND_EQUAL_CONSTANT).append(conditionOperationList.get(i).getValue());
                    break;
                case ELConstant.EL_FRONT_EQUAL_CONSTANT:
                    if (conditionOperationList.get(i).getFormKey().contains(FormComponentConstants.MULTIPLE_SELECTION_COMPONENT)) {
                        valueStr = conditionOperationList.get(i).getValue();
                        List<String> lists = JSONArray.parseArray(valueStr, String.class);
                        if (ObjectUtils.isNotEmpty(lists)) {
                            StringBuilder valueSB = new StringBuilder();
                            valueSB.append("\"").append(StringUtils.join(lists, LanguageExpressionConstants.LANGUAGE_COMMA)).append("\"");
                            elExpression.append(conditionOperationList.get(i).getFormKey()).append(ELConstant.EL_EQUAL_CONSTANT).append(valueSB);
                        }
                    } else {
                        elExpression.append(conditionOperationList.get(i).getFormKey()).append(ELConstant.EL_EQUAL_CONSTANT).append(conditionOperationList.get(i).getValue());
                    }
                    break;
                case ELConstant.EL_IN_CONSTANT:
                    valueStr = conditionOperationList.get(i).getValue();
                    List<String> valueList = JSONArray.parseArray(valueStr, String.class);
                    StringBuilder optionSb = new StringBuilder();
                    if (StringUtils.isBlank(optionSb.toString())) {
                        optionSb.append(ELConstant.EL_FRONT_BRACKET_CONSTANT);
                    }
                    for (int j = 0; j < valueList.size(); j++) {
                        optionSb.append(conditionOperationList.get(i).getFormKey()).append(ELConstant.EL_EQUAL_CONSTANT).append("\"").append(valueList.get(j))
                                .append("\"").append(ELConstant.EL_BLANK_CONSTANT);
                        if (j < valueList.size() - 1) {
                            optionSb.append(ELConstant.EL_OR_CONSTANT);
                        }
                        if (j == valueList.size() - 1) {
                            optionSb.append(ELConstant.EL_END_BRACKET_CONSTANT);
                        }
                    }
                    elExpression.append(optionSb);
                    break;
                case ELConstant.EL_BETWEEN_CONSTANT:
                    valueStr = conditionOperationList.get(i).getValue();
                    JSONArray jsonArray = JSONArray.parseArray(valueStr);
                    elExpression.append(ELConstant.EL_FRONT_BRACKET_CONSTANT).append(conditionOperationList.get(i).getFormKey()).append(logicReverse(String.valueOf(conditionOperationList.get(i).getExtraOperation().get(0)))).append(jsonArray.get(0))
                            .append(ELConstant.EL_BLANK_CONSTANT).append(ELConstant.EL_AND_CONSTANT).append(ELConstant.EL_BLANK_CONSTANT).append(conditionOperationList.get(i).getFormKey())
                            .append(conditionOperationList.get(i).getExtraOperation().get(1)).append(jsonArray.get(1)).append(ELConstant.EL_END_BRACKET_CONSTANT);
                    break;
                case ELConstant.EL_INCLUDE_CONSTANT:
                    valueStr = conditionOperationList.get(i).getValue();
                    List<String> lists = JSONArray.parseArray(valueStr, String.class);
                    Collections.sort(lists);
                    CombinationIterator<String> valueCombinationIterator = new CombinationIterator<>(lists);
                    StringBuilder includeSb = new StringBuilder();
                    includeSb.append(ELConstant.EL_FRONT_BRACKET_CONSTANT);
                    while (valueCombinationIterator.hasNext()) {
                        if (includeSb.length() > 1) {
                            includeSb.append(ELConstant.EL_BLANK_CONSTANT).append(ELConstant.EL_OR_CONSTANT).append(ELConstant.EL_BLANK_CONSTANT);
                        }
                        Object obj = valueCombinationIterator.next();
                        if (ObjectUtils.isNotEmpty(String.valueOf(obj))) {
                            includeSb.append(conditionOperationList.get(i).getFormKey()).append(ELConstant.EL_EQUAL_CONSTANT).append("\"").append(obj).append("\"");
                        }
                    }
                    includeSb.append(ELConstant.EL_END_BRACKET_CONSTANT);
                    elExpression.append(includeSb);
                    break;
                default:
                    continue;
            }
            if (i < length - 1) {
                elExpression.append(ELConstant.EL_BLANK_CONSTANT).append(ELConstant.EL_AND_CONSTANT).append(ELConstant.EL_BLANK_CONSTANT);
            }
        }
        elExpression.append(ELConstant.EL_END_BRACE_CONSTANT);
        log.info("EL expression :" + elExpression);
        return elExpression.toString();
    }

    private static String logicReverse(String operation) {
        switch (operation) {
            case ELConstant.EL_BIGGER_CONSTANT:
                return ELConstant.EL_SMALLER_CONSTANT;
            case ELConstant.EL_SMALLER_CONSTANT:
                return ELConstant.EL_BIGGER_CONSTANT;
            case ELConstant.EL_BIGGER_AND_EQUAL_CONSTANT:
                return ELConstant.EL_SMALLER_AND_EQUAL_CONSTANT;
            case ELConstant.EL_SMALLER_AND_EQUAL_CONSTANT:
                return ELConstant.EL_BIGGER_AND_EQUAL_CONSTANT;
            default:
                return "";
        }
    }

}
